#include <cstdlib>
#include <unistd.h>
#include <sys/param.h>
#include <XrddmConfig.h>
#include <XrdDownloadManagerLog.hh>
// #include <XrdDownloadManagerBase.hh>
#include <XrdDownloadManagerAliEn.hh>

XrdDownloadManagerLog *gLogDM = 0;

int setLogFile ( string logFile );
void help();
int main ( int argc, char **argv ) {
    
//     XrdDownloadManagerBase obj;
//     unsigned int rndNums[3];
//     obj.GenerateRandomNumbers(&rndNums[0],3);
//     return 0;
    
    XrdDownloadManagerLog::Init();

//     XrdDMLogGInfo("Hello2 ...");

    int c,debuglevel=-1,debuglevelG=-1;

    string mystr,configfile,logfile,sourcestr,logdir,stried;
    bool useAuthentication = false;
    bool useXrdcpInLogFile = false;
    bool useRemoveLogAfterSuccessCopy = false;
    bool useRemoveLogDirAfterSuccessCopy = false;
    bool useRandomizeFilelist = false;
    opterr = 0;
//     while ( ( c = getopt ( argc, argv, "c:l:d:x:masfnA" ) ) != -1 )
    while ( ( c = getopt ( argc, argv, "c:s:d:D:L:l:t:arRS" ) ) != -1 )
        switch ( c ) {
        case 'c':
            configfile = optarg;
            break;
        case 's':
            sourcestr = optarg;
            break;
        case 'd':
            mystr = optarg;
            debuglevel = atoi ( mystr.c_str() );
//             useXrdcpInLogFile = true;
            XrdDMLogGDebugFull ( "Using option : -d %d",debuglevel );
            break;
        case 'D':
            mystr = optarg;
            debuglevelG = atoi ( mystr.c_str() );
            XrdDMLogGDebugFull ( "Using option : -D %d",debuglevelG );
            break;
        case 'L':
            logfile = optarg;
            break;
        case 'l':
            logdir = optarg;
            useXrdcpInLogFile = true;
            break;
        case 't':
            stried = optarg;
            break;
        case 'a':
            useAuthentication = true;
            break;
        case 'r':
            useRemoveLogAfterSuccessCopy = true;
            break;
        case 'R':
            useRemoveLogDirAfterSuccessCopy = true;
            break;
        case 'S':
            useRandomizeFilelist = true;
            break;
        case ':':
            XrdDMLogGFatal ( "Option '-%c' requires an argument", optopt );
            help();
            return 11;
            break;
        case '?':
            XrdDMLogGFatal ( "Unknown option: '-%c'", optopt );
            help();
            return 12;
        default:
            XrdDMLogGFatal ( "Abort with '%c'", optopt );
            abort ();
        }
        
    string filestr[2];
    int i=0;
    for ( int index = optind; index < argc; index++ ) {
        filestr[i++] = argv[index];
    }

    // checks that that we have 2 filenames defined
    if ( argc-optind != 2 ) {
        help();
        return 1;
    }

    //setting global debug level
    if ( debuglevelG>=0 ) {
        gLogDM->SetDebug ( debuglevelG );
    }

    XrdDownloadManagerBase *dm=0;
    if ( !strcmp ( XrdDownloadManagerBase::GetXrdType ( filestr[0].c_str() ).c_str(),"alien" ) ) {
        XrdDMLogGDebugFull ( "Using XrdDownloadManagerAliEn ..." );
        dm = new XrdDownloadManagerAliEn();
    } else {
        XrdDMLogGDebugFull ( "Using XrdDownloadManagerBase ..." );

        dm = new XrdDownloadManagerBase();
    }

//     XrdDMLogGDebugMedium ( "Filename is %s ...",filestr[0].c_str() );
//     return 0;

// XrdDownloadManagerAliEn* dm = new XrdDownloadManagerAliEn();

    // setting log file
    if ( !logfile.empty() ) {
        dm->SetGlobalLogFile(logfile.data());
//         XrdDMLogGInfo("Log file is %s",logfile.c_str());
        if ( setLogFile ( logfile.c_str() ) ) return 32;
        close ( STDIN_FILENO );
        close ( STDOUT_FILENO );
        close ( STDERR_FILENO );
    }


    // setting vonfig filr
    if ( !configfile.empty() )
        dm->ReadConfigFile ( configfile );

    if ( !sourcestr.empty() )
        dm->SetSourceTypes ( sourcestr.c_str() );

    // setting use auth
    dm->UseAuthentication ( useAuthentication );

    // use xrdcp process log dir
    if ( !logdir.empty() )
        dm->SetLogDirectory ( logdir );
    // use xrdcp process log file
    dm->DoXrdcpInLogFile ( useXrdcpInLogFile ,debuglevel,filestr[0].c_str());

    // -0Stried option
    dm->SetXrdcpCmdCn ( stried );

    // use Remove Log After Success Copy
    dm->UseRemoveLogAfterSuccessCopy ( useRemoveLogAfterSuccessCopy );

    // use Remove Log directory After Success Copy
    dm->UseRemoveLogDirectoryAfterSuccessCopy ( useRemoveLogDirAfterSuccessCopy );
    
    dm->RandomizeFilelist(useRandomizeFilelist);

    XrdDMLogGDebugFull ( "Filename is %s ...",filestr[0].c_str() );

    XrdDMLogGDebugFull ( "Type : %s",dm->GetXrdType ( filestr[0].c_str() ).c_str() );
    XrdDMLogGDebugFull ( "Host : %s",dm->GetXrdHost ( filestr[0].c_str() ).c_str() );
    XrdDMLogGDebugFull ( "Port : %s",dm->GetXrdPort ( filestr[0].c_str() ).c_str() );
    XrdDMLogGDebugFull ( "File : %s",dm->GetXrdFilename ( filestr[0].c_str() ).c_str() );

    if ( !dm->IsFileNameValid ( filestr[0].c_str() ) ) {
        help();
        return 2;
    }

    XrdDMLogGDebugFull ( "Filename %s is valid ...",filestr[0].c_str() );

    XrdDMLogGInfo ( "xrddm [%s] started ...",filestr[0].c_str(),filestr[1].c_str() );
    
    int retVal = dm->DoCopy ( filestr[0].c_str() ,filestr[1].c_str() );

    XrdDMLogGInfo ( "xrddm [%s] return vaule is %d ...",filestr[0].c_str(),retVal );
//     return 0;
    // cleaning logs
    XrdDownloadManagerLog::Delete();

    // deleting download manager
    delete dm;

    return retVal;
}

int setLogFile ( string logFile ) {

    if ( logFile.empty() ) return 0;

    string logFileAbsolute;
    // Check if log filename is absolute
    if ( ( !logFile.empty() ) && ( logFile.find_first_of ( "/" ) ) ) {
        char path[MAXPATHLEN];
        getcwd ( path, MAXPATHLEN );
        logFileAbsolute = path;
        logFileAbsolute += "/";
        logFileAbsolute += logFile.c_str();
    } else {
        logFileAbsolute = logFile.c_str();
    }

    string logdircmd ( "mkdir -p " );
    logdircmd.append ( logFileAbsolute.c_str() );
    logdircmd.erase ( logdircmd.find_last_of ( "/" ),logdircmd.length() );
    int retValMkdir = system ( logdircmd.c_str() );
    if ( retValMkdir ) {
        XrdDMLogGError ( "%s retValMkdir val is %d",logdircmd.c_str(),retValMkdir );
        retValMkdir = system ( "mkdir -p /tmp/xrddm/" );
        XrdDMLogGError ( "Trying to create default dir 'mkdir -p /tmp/xrddm/' retValMkdir is %d",retValMkdir );
        logFileAbsolute = "/tmp/xrddm/";
        logFile.erase ( logFile.find_last_of ( "/" ),logFile.length() );
        logFileAbsolute = logFile;
    }

    //umask(0);
    chdir ( "/" );

    XrdDMLogGDebugMedium ( "Final Log File is  %s ",logFileAbsolute.c_str() );
    if ( !logFileAbsolute.empty() ) {
        if ( !gLogDM->SetFile ( logFileAbsolute.c_str() ) ) {
            XrdDMLogGError ( "Error creating %s !!!",logFileAbsolute.c_str() );
            help();
            return 21;  // no error message can be seen at this point, it is pointless
            // to print something
        }
    }
    return 0;
}

void help() {
    XrdDMLogGFatal ( "Error !!!" );
    XrdDMLogGInfo ( "\tUsage: xrddm root://<host>:<port>/<filename> <to>" );
    XrdDMLogGInfo ( "\tUsage: xrddm alien://<filename> <to>" );
    XrdDMLogGInfo ( "" );
    XrdDMLogGInfo ( "Options :" );
    XrdDMLogGInfo ( "  -a                  : Do AliEn token automaticaly" );
    XrdDMLogGInfo ( "  -L <filename>       : Do Global log file" );
    // TODO optional switch for -l
    XrdDMLogGInfo ( "  -l <dir>            : Do log file for download process." );
    XrdDMLogGInfo ( "  -d <debug level>    : Enable debug" );
    XrdDMLogGInfo ( "  -D <global debug level>    : Enable debug" );
    XrdDMLogGInfo ( "  -s <mode1>,<modeN>  : Run with different download modes" );
    XrdDMLogGInfo ( "                      - 'std' is for standard xrdcp" );
    XrdDMLogGInfo ( "                      - 'alien' is for alien_cp" );
    XrdDMLogGInfo ( "" );

    XrdDownloadManagerLog::Delete();
}
// kate: indent-mode cstyle; space-indent on; indent-width 4; 
